home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Think Class Libraries / WASTE TCL 1.8 / WASTE TCL 1.8 ƒ / CWASTEEditTask.cp < prev    next >
Encoding:
Text File  |  1995-11-12  |  8.6 KB  |  385 lines  |  [TEXT/MMCC]

  1. /*
  2.  *
  3.  *    File:        CWASTEEditTask.cp
  4.  *    Module:        CWASTEEditTask method definitions
  5.  *    System:        Mark's Class Library
  6.  *    Evironment:    MacOS 7.0/THINK C 7.0/TCL 2.0
  7.  *    Author:        Mark Alldritt
  8.  *
  9.  *
  10.  *        Copyright © 1994    All Rights Reserved
  11.  *        Mark Alldritt
  12.  *        1571 Deep Cove Road
  13.  *        N. Vancouver, B.C. CANADA
  14.  *
  15.  *    
  16.  *    Description:
  17.  *
  18.  *  This class modifies the CTextEditTask to allow it to work with CWASTEText.
  19.  *
  20.  *
  21.  *    Acknowledgemets:
  22.  *
  23.  *    None.
  24.  *
  25.  *
  26.  *    Notes:
  27.  *
  28.  *
  29.  *    Edit History:
  30.  *
  31.  *    V1-0.0    Mark Alldritt    10-May-1994
  32.  *    - Initial version of module.
  33.  *  V1.0.1  Modifications by Dan Crevier to TCL 2.0
  34.  *  V1.0.2  Added code by Mark Alldritt for undo/redo
  35.  *
  36.  *            Adapted to THINK C / TCL 1.1.3     (Roms, 95/11/08)
  37.  *
  38.  */
  39.  
  40.  
  41. #include "CWASTEText.h"
  42. #include "CWASTEEditTask.h"
  43.  
  44. #include <CClipboard.h>
  45.  
  46. extern CClipboard *gClipboard;
  47.  
  48. #ifndef THINK_C
  49. CWASTEEditTask::CWASTEEditTask(CWASTEText *aTextPane, long anEditCmd, 
  50.                                short firstTaskIndex)
  51. #else
  52. void CWASTEEditTask::IWASTEEditTask(CWASTEText *aTextPane, long anEditCmd, 
  53.                                short firstTaskIndex)
  54. #endif // THINK_C
  55.  
  56. {
  57.     Handle    h;
  58.     
  59.     origStyleScrap = deletedStyles = insertedStyles = NULL;
  60.  
  61.     // can't call through constructor, or our SaveRange won't be called
  62.     ITextEditTask( aTextPane, anEditCmd, firstTaskIndex);
  63.  
  64.     gClipboard->GetData( 'styl', &h);
  65.     origStyleScrap = (StScrpHandle) h;
  66.  
  67. }
  68.  
  69.  
  70. #ifndef THINK_C
  71. CWASTEEditTask::~CWASTEEditTask()
  72. #else
  73. void CWASTEEditTask::Dispose()
  74. #endif // THINK_C
  75. {
  76.     ForgetHandle( origStyleScrap);
  77.     ForgetHandle( deletedStyles);
  78.     ForgetHandle( insertedStyles);
  79.     
  80. #ifdef THINK_C
  81.     CTextEditTask::Dispose();
  82. #endif
  83.  
  84. }
  85.  
  86.  
  87. void CWASTEEditTask::SaveRange( tRangeSelector whichRange)
  88. {
  89.     StScrpHandle    h;
  90.     
  91.     inherited::SaveRange( whichRange);
  92.     
  93.     /* what we need to do is to copy the sel starts and ends and styles
  94.     either of what was inserted or deleted  mfnov 1994*/
  95.     
  96.     
  97.     h=(StScrpHandle)NewHandleCanFail(1);
  98.     FailNIL(h);
  99.  
  100.     if (whichRange == kInsertedRange)
  101.         ((CWASTEText*) itsTextPane)->CopyRangeWithStyle(inserted.start,inserted.end, (Handle)NULL,
  102.             h);
  103.     else
  104.         ((CWASTEText*) itsTextPane)->CopyRangeWithStyle(deleted.start,deleted.end, (Handle)NULL,
  105.             h);
  106.             
  107.     if (whichRange == kInsertedRange)
  108.         insertedStyles = h;
  109.     else
  110.         deletedStyles = h;
  111.                                 
  112.                                 
  113.     
  114. /* OLD    itsTextPane->GetSelection( &oldStart, &oldEnd);
  115.     
  116.     if (whichRange == kInsertedRange)
  117.         itsTextPane->SetSelection( inserted.start, inserted.end, FALSE);
  118.     else
  119.         itsTextPane->SetSelection( deleted.start, deleted.end, FALSE);
  120.         
  121.     h = ((CWASTEText*) itsTextPane)->GetTheStyleScrap();
  122.     
  123.     itsTextPane->SetSelection( oldStart, oldEnd, FALSE);
  124.     
  125.     if (whichRange == kInsertedRange)
  126.         insertedStyles = h;
  127.     else
  128.         deletedStyles = h;  */
  129.     
  130. }
  131.  
  132.  
  133. void CWASTEEditTask::RestoreRange( tRangeSelector whichRange, Boolean killData)
  134. {
  135.     Handle            text;
  136.     StScrpHandle     styles;
  137.     long            selStart, selEnd, start;
  138.     short            styleFixup;
  139.     
  140.     if (whichRange == kInsertedRange)
  141.     {
  142.         text = inserted.text;
  143.         styles = insertedStyles;
  144.         start = inserted.start;
  145.         selStart = inserted.selStart;
  146.         selEnd = inserted.selEnd;
  147.         if (killData)
  148.         {
  149.             inserted.text = NULL;
  150.             insertedStyles = NULL;
  151.         }
  152.     }
  153.     else
  154.     {
  155.         text = deleted.text;
  156.         styles = deletedStyles;
  157.         start = deleted.start;
  158.         selStart = deleted.selStart;
  159.         selEnd = deleted.selEnd;
  160.         if (killData)
  161.         {
  162.             deleted.text = NULL;
  163.             deletedStyles = NULL;
  164.         }
  165.     }
  166.     
  167.     if (text)
  168.     {
  169.         // Due to backspacing, the save styled scrap handle may
  170.         // begin with negative offsets. Before attempting to
  171.         // restore these styles we must fix up the offsets
  172.         // to start at 0.
  173.         
  174.         styleFixup = -(**styles).scrpStyleTab[0].scrpStartChar;
  175.         if (styleFixup > 0)
  176.         {
  177.             ScrpSTElement    *table = (**styles).scrpStyleTab;
  178.             short i = (**styles).scrpNStyles;
  179.             
  180.             while (--i >= 0)
  181.             { 
  182.                 table++->scrpStartChar += styleFixup;
  183.             }
  184.         }
  185.  
  186.         itsTextPane->SetSelection( start, start, TRUE);
  187.         MoveHHi( text);
  188.         HLock( text);
  189.         ((CWASTEText *)itsTextPane)->InsertWithStyle(*text, GetHandleSize( text), styles, FALSE);
  190.         HUnlock( text);
  191.     }
  192.     if (killData)
  193.     {
  194.         ForgetHandle(text);
  195.         ForgetHandle( styles);
  196.     }
  197.     itsTextPane->SetSelection( selStart, selEnd, TRUE);
  198.  
  199. }
  200.  
  201.  
  202. void CWASTEEditTask::StoreToClip( tClipSelector whichClip)
  203. {
  204.     StScrpHandle     h;
  205.  
  206.     inherited::StoreToClip( whichClip);
  207.         
  208.     if (whichClip == kOldClip)
  209.         h = origStyleScrap;
  210.     else
  211.         h = deletedStyles;
  212.  
  213.     if (h)
  214.         gClipboard->PutData( 'styl', (Handle) h);
  215.         
  216.  
  217. }
  218.  
  219.  
  220. void CWASTEEditTask::DoBackspace( void)
  221. {
  222.     long             selStart, selEnd;
  223.     ScrpSTElement     scrapEl;
  224.     WERunInfo        runInfo;
  225.     
  226.     itsTextPane->GetSelection( &selStart, &selEnd);
  227.     
  228.     /*
  229.      *    We only need to do something when the user is backspacing
  230.      *  over original text that was not selected at the start
  231.      *  of this task. When that happens, we must check the style
  232.      *  of the char being deleted. If it is different from the
  233.      *  style currently at the front of the deletedStyle handle
  234.      *  then we must insert it to the handle.
  235.      */
  236.     
  237.     if ((selStart > 0) && (selStart == deleted.start) && (selStart == selEnd))
  238.     {
  239.         WEGetRunInfo(selStart - 1, &runInfo, ((CWASTEText *)itsTextPane)->macWE);
  240.         
  241.         /* make up a style scrap element for the char to be deleted.    */
  242.         /* Then we'll see if it matches the first style in the            */
  243.         /* saved scrap. If not, we need to insert it to the scrap        */
  244.         
  245.         scrapEl.scrpStartChar = (**deletedStyles).scrpStyleTab[0].scrpStartChar-1;
  246.         scrapEl.scrpHeight = runInfo.runHeight;
  247.         scrapEl.scrpAscent = runInfo.runAscent;
  248.         /* remaining fields are equivalent to a TextStyle record    */
  249.         *(TextStyle*) &scrapEl.scrpFont = runInfo.runStyle;
  250.         
  251.         /* CheckNewStyle inserts the new style at the head of the    */
  252.         /* style scrap if its new. Otherwise, we just decrement        */
  253.         /* the starting offset for the first style. This is            */
  254.         /* faster than running through the whole table, fixing        */
  255.         /* up offsets each time the user backspaces, but we have    */
  256.         /* to be sure and fix these up later, before attempting to    */
  257.         /* use these styles                                            */
  258.         
  259.         if (!CheckNewStyle( &scrapEl, deletedStyles, TRUE))        
  260.             (**deletedStyles).scrpStyleTab[0].scrpStartChar--;
  261.     }
  262.  
  263.     inherited::DoBackspace();
  264. }
  265.  
  266.  
  267. void CWASTEEditTask::DoFwdDelete( void)
  268. {
  269.     long             selStart, selEnd, length;
  270.     ScrpSTElement     scrapEl;
  271.     WERunInfo        runInfo;
  272.     
  273.     itsTextPane->GetSelection( &selStart, &selEnd);
  274.     length = itsTextPane->GetLength();
  275.     
  276.     if ((selStart == selEnd) && (selEnd < length))
  277.     {
  278.         WEGetRunInfo(selStart - 1, &runInfo, ((CWASTEText *)itsTextPane)->macWE);
  279.  
  280.         /* make up a style scrap element for the char to be deleted.    */
  281.         /* Then we'll see if it matches the last style in the            */
  282.         /* saved scrap. If not, we need to insert it to the scrap        */
  283.         
  284.         scrapEl.scrpStartChar = deleted.end - deleted.start + 
  285.                     (**deletedStyles).scrpStyleTab[0].scrpStartChar;
  286.         scrapEl.scrpHeight = runInfo.runHeight;
  287.         scrapEl.scrpAscent = runInfo.runAscent;
  288.         /* remaining fields are equivalent to a TextStyle record    */
  289.         *(TextStyle*) &scrapEl.scrpFont = runInfo.runStyle;
  290.         
  291.         CheckNewStyle( &scrapEl, deletedStyles, FALSE);    
  292.     }
  293.     inherited::DoFwdDelete();
  294. }
  295.  
  296.  
  297. Boolean CWASTEEditTask::CheckNewStyle(ScrpSTElement *scrapEl, 
  298.                                       StScrpHandle styleH,
  299.                                       Boolean atStart)
  300. {
  301.     short     index = atStart ? 0 : (**styleH).scrpNStyles-1;
  302.     long    currSize;
  303.     Boolean wasNew = FALSE;
  304.     
  305.     /* compare scrapEl with either first or last scrapElement in scrap handle    */
  306.     /* but don't compare the scrpStartChar fields                                */
  307.     /* If they don't match, then a new ScrpSTElement is inserted                */
  308.     
  309.     if (!EqualMem( &scrapEl->scrpHeight, 
  310.             &(**styleH).scrpStyleTab[index].scrpHeight, 
  311.             sizeof(TextStyle) - sizeof(long)))
  312.     {
  313.             
  314.         currSize = GetHandleSize( (Handle) styleH);
  315.         ResizeHandleCanFail( (Handle) styleH, currSize + sizeof(ScrpSTElement));
  316.         FailMemError();
  317.         
  318.         /* if atStart, then move old styles down            */
  319.         
  320.         if (atStart)
  321.         {
  322.             BlockMove( &(**styleH).scrpStyleTab[0],
  323.                     &(**styleH).scrpStyleTab[1],
  324.                     currSize - sizeof(short));
  325.         }
  326.         else
  327.             index++; // place at end
  328.         
  329.         /* place new style in position, increment count        */
  330.         
  331.         (**styleH).scrpStyleTab[index] = *scrapEl;
  332.         (**styleH).scrpNStyles++;
  333.                 
  334.         wasNew = TRUE;
  335.     }
  336.  
  337.     return wasNew;
  338. }
  339.  
  340. /*
  341. void CWASTEEditTask::Undo()
  342. {   inherited::Undo();
  343.     CTask::Undo();
  344.     
  345.     if (doText)
  346.     {
  347.         if (stillTyping)
  348.             CancelTyping();
  349.  
  350.         SaveRange(kInsertedRange);
  351.     
  352.         itsTextPane->Prepare();
  353.         itsTextPane->SetSelection(inserted.start, inserted.end, FALSE);
  354.         RestoreRange(kDeletedRange, FALSE);
  355.     }
  356.     
  357.     if (doClip)
  358.         StoreToClip(kOldClip);
  359. }
  360.  */
  361. /*
  362. void CWASTEEditTask::Redo()
  363. {
  364.     undone = FALSE;
  365.     if (editCmd == cmdNull) stillTyping = TRUE;
  366.  
  367.     if (doText)
  368.     {
  369.         itsTextPane->Prepare();
  370.         itsTextPane->SetSelection(deleted.start, deleted.end, FALSE);
  371.         RestoreRange(kInsertedRange, TRUE);
  372.  
  373.         if (editCmd == cmdNull)
  374.             stillTyping = TRUE;
  375.     }
  376.  
  377.     if (doClip)
  378.         StoreToClip(kNewClip);
  379.  
  380.     ReportChange(TRUE);
  381. }
  382.  
  383. */
  384.  
  385.